<?php

namespace App\Service\OpenShop\SiteLocation;

use App\Enums\OpenShop\InvestmentPromotion\SiteLocationEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Guanyuan\GuanyuanTool;
use App\Models\Guanyuan\GuanyuanSyncShopBusinessModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use Ballen\Distical\Calculator as DistanceCalculator;
use Ballen\Distical\Entities\LatLong;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;


class GuanyuanDataService
{

    private static int $timeout = 5;


    //设置超时时间
    public static function setTimeOut(int $timeout)
    {
        self::$timeout = $timeout;
    }

    /**
     * 城市店租水平
     * @return array
     */
    public static function restaurantRents(): array
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:restaurantRents', 600, function (){
            return GuanyuanTool::fetch('s580b6c8918224fdfa8da24b', 'i99f447954eda4fba85c2271', [], self::$timeout);
        });
    }

    /**
     * 门店列表
     * @return array
     */
    public static function shopList(): array
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:shopList', 600, function (){
            return GuanyuanTool::fetch('r908e1ee76add42668f1adfc', 'de01da3ecf39743d895db6c6', [], self::$timeout);
        });
    }

    /**
     * 省区目标
     * @return array
     */
    public static function provinceTargets(): array
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:provinceTargets', 600, function (){
            return GuanyuanTool::fetch('h2941149450b640038df6b30', 'ea113cfc6b92d4581bc4acbc', [], self::$timeout);
        });
    }

    /**
     * 在营门店明细
     * @return mixed
     */
    public static function ingShops()
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:ingShops', 600, function (){

            $params = [
                [
                    'name' => '本月在营门店数',
                    'filterType' => 'NE',
                    'filterValue' => [
                        null,
                    ],
                ]
            ];

            return GuanyuanTool::fetch('bced09b403c854bd9a3f20f7', 't91ce78b6abb045429bae60e', $params);
        });
    }

    /**
     * 算出最靠近的门店
     * @param float $latitude 纬度
     * @param float $longitude 经度
     * @return null|array  距离单位是千米
     */
    public static function closestShop(float $latitude, float $longitude, string $city = '', bool $shopStatus = true): ?array
    {
        try {
            static::$timeout = 20;
            $list = static::newShopList();
        } catch (\Exception $exception) {
            $list = [];
        }
        foreach ($list as $k => $v) {
            $list[$k]['门店经度'] = $v['门店经度'] = trim($v['门店经度']);
            $list[$k]['门店纬度'] = $v['门店纬度'] = trim($v['门店纬度']);
            if (!is_numeric($v['门店经度'])) {
                unset($list[$k]);
                continue;
            }
//            if (null === ($v['门店名称'] ?? null)) {
//                unset($list[$k]);
//                continue;
//            }
            if (!is_numeric($v['门店纬度'])) {
                unset($list[$k]);
                continue;
            }
            if ($v['门店经度'] < -180 || $v['门店经度'] > 180) {
                unset($list[$k]);
                continue;
            }
            if ($v['门店纬度'] < -90 || $v['门店纬度'] > 90) {
                unset($list[$k]);
                continue;
            }
            if (mb_strlen($city) && $v['门店所在市'] != $city) {
                unset($list[$k]);
                continue;
            }
            if (!in_array($v['状态'], ['筹备中', '正常营业', '暂停营业'])) {
                unset($list[$k]);
                continue;
            }

            if (abs($latitude - $v['门店纬度']) < 0.0001 && abs($longitude - $v['门店经度']) < 0.0001) {
                $list[$k]['distance'] = 0.01;
            } else {
                $list[$k]['distance'] = (new DistanceCalculator(
                    new LatLong($latitude, $longitude),
                    new LatLong($v['门店纬度'], $v['门店经度'])
                ))->get()->asKilometres();
            }
            if ($list[$k]['distance'] == 0.01) {
                unset($list[$k]);
            }
            $list[$k]['address'] = $v['店铺地址'];
        }
        if (!count($list)) {
            return [
                'name'     => '该城市内无夸父门店',
                'code'     => '0000',
                'distance' => 0,
            ];
        }
        $shop = collect($list)->sortBy('distance')->first();

        if ($shopStatus) {
            if (isset($shop['状态']) && isset($shop['门店名称'])) {
                $name = '【' . $shop['状态'] .  '】' . $shop['门店名称'];
            } else {
                $name = '该城市内无夸父门店';
            }
        } else {
            $name = $shop['门店名称'] ?? '-';
        }

        return [
            'name'     => $name,
            'code'     => $shop['铺位号'] ?? '0000',
            'distance' => $shop['distance'] ?? 0,
            'address'  => $shop['address'] ?? '-',
        ];
    }

    /**
     * 等级城市 租金范围
     * @param string $level   例如：一线、新一线、二线、三线、四线、五线
     * @return array|null     如果查询不到返回null
     */
    public static function levelCityRentRange(string $level): ?array
    {
        $items = [];
        try {
            foreach (static::restaurantRents() as $item) {
                if ($item['城市等级'] == $level) {
                    $items[] = $item;
                }
            }
        } catch (\Exception $exception) {
            throw new ResponseHttpException(504, null, '观远超时,租金范围获取失败,请稍后再试');
        }
        if (!count($items)) {
            return null;
        }
        // 计算上四分位数、下四分位数
        $rentNumbers = collect($items)->pluck('房租成本')->sort()->values()->toArray();
        if (1 == count($rentNumbers)) {
            $minFourNumber = $rentNumbers[0];
            $maxFourNumber = $rentNumbers[0];
        } else {
            $minPosition    = count($rentNumbers) * 0.25;
            $maxPosition    = count($rentNumbers) * 0.75;
            $minPointNumber = $minPosition - floor($minPosition);
            $maxPointNumber = $maxPosition - floor($maxPosition);
            $minFourNumber  = $rentNumbers[floor($minPosition) - 1] * $minPointNumber
                + $rentNumbers[floor($minPosition)] * (1 - $minPointNumber);
            $maxFourNumber  = $rentNumbers[floor($maxPosition) - 1] * $maxPointNumber
                + $rentNumbers[floor($maxPosition)] * (1 - $maxPointNumber);
        }
        return compact('minFourNumber', 'maxFourNumber');
    }

    /**
     * 城市租金性价比参考
     * @param string $orderNo
     * @return int|null
     */
    public static function levelCityRentCostPerformance(string $orderNo): ?int
    {
        $site = OpenShopSiteLocationModel::query()
                                         ->where('orderNo', $orderNo)
                                         ->whereIn('source',
                                             [
                                                 OpenShopSiteLocationModel::SOURCE_OPEN_SHOP,
                                                 OpenShopSiteLocationModel::SOURCE_HOUSING
                                             ])
                                         ->select('cityType', 'clueRent')
                                         ->first();
        if (!$site) {
            return null;
        }

        $level = $site->cityType;
        $rent  = (int)($site->clueRent / 100 / 12);
        $levelText = SiteLocationEnum::CITY_TYPE_LEVEL_TEXT[$level] ?? '';

        $standard = static::levelCityRentRange($levelText);

        if (null === $standard) {
            return null;
        }
        if ($rent < $standard['minFourNumber']) {
            return SiteLocationEnum::COST_PERFORMANCE_HIGH;
        }
        if ($rent > $standard['maxFourNumber']) {
            return SiteLocationEnum::COST_PERFORMANCE_LOW;
        }
        return SiteLocationEnum::COST_PERFORMANCE_MEDIUM;
    }

    /**
     * 获得开店选址数据
     * @return mixed
     */
    public static function getSiteOpenShopData()
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:openShop', 600, function (){
            return GuanyuanTool::fetch('c03f0050ebc284ae68f27084', 'r2c6baea3b82d4c259f12fa3', [], self::$timeout);
        });
    }

    /**
     * 获得房源线索数据
     * @return mixed
     */
    public static function getSiteHouseClueData()
    {
        return Cache::remember('tiger:openShop:siteLocation:guanyuan:houseClue', 600, function (){
            return GuanyuanTool::fetch('sc466f2f25f8b4987bf266e0', 'i19fd1c33376b4c15807c923', [], self::$timeout);
        });
    }


    /**
     * 根据城市获得商场数据
     * @param array $mallIds
     * @return array
     * @throws GuzzleException
     */
    public static function getMallDataByCity(array $mallIds): array
    {
        $params = [
            [
                'name' => '商场ID',
                'filterType' => 'IN',
                'filterValue' => $mallIds,
            ]
        ];
        return GuanyuanTool::fetch('g92a48a33b6d64046a463728', 'e99b29b8ee36446998829d70', $params, self::$timeout);
    }

    /**
     * 根据商场ID获得商场数据
     * @param string $mallId
     * @return array
     * @throws GuzzleException
     */
    public static function getMallDataByMallId(string $mallId): array
    {
        $params = [
            [
                'name' => '商场ID',
                'filterType' => 'EQ',
                'filterValue' => [
                    $mallId
                ],
            ]
        ];
        return GuanyuanTool::fetch('g92a48a33b6d64046a463728', 'e99b29b8ee36446998829d70', $params, self::$timeout);
    }

    /**
     * 区级容量
     * @return array
     */
    public static function districtVolume(): array
    {
        return Cache::remember('tiger:openShop:map:guanyuan:districtVolume', 600, function (){
            return GuanyuanTool::fetch('q5715dfcb80c547a5a07f843', 'b3807a603506a4a8ba337042', [], self::$timeout);
        });
    }


    /**
     * 附近的夸父门店
     * @param float $latitude 纬度
     * @param float $longitude 经度
     * @param int $distance
     * @param string $city
     * @param int|string $shopCode
     * @return array  距离单位是千米
     */
    public static function nearbyShop(float $latitude, float $longitude, int $distance = 3, string $city = '', $shopCode = 0): array
    {
        try {
            static::$timeout = 20;
            $list = static::newShopList();
        } catch (\Exception $exception) {
            return [];
        }
        $data = [];
        foreach ($list as $k => $v) {
            $list[$k]['门店经度'] = $v['门店经度'] = trim($v['门店经度']);
            $list[$k]['门店纬度'] = $v['门店纬度'] = trim($v['门店纬度']);
            if (!is_numeric($v['门店经度'])) {
                unset($list[$k]);
                continue;
            }
            if (!is_numeric($v['门店纬度'])) {
                unset($list[$k]);
                continue;
            }
            if ($v['门店经度'] < -180 || $v['门店经度'] > 180) {
                unset($list[$k]);
                continue;
            }
            if ($v['门店纬度'] < -90 || $v['门店纬度'] > 90) {
                unset($list[$k]);
                continue;
            }
            if (mb_strlen($city) && $v['门店所在市'] != $city) {
                unset($list[$k]);
                continue;
            }
            if (!in_array($v['状态'], ['筹备中', '正常营业', '暂停营业'])) {
                unset($list[$k]);
                continue;
            }

            if (abs($latitude - $v['门店纬度']) < 0.0001 && abs($longitude - $v['门店经度']) < 0.0001) {
                $list[$k]['distance'] = 0.01;
            } else {
                $list[$k]['distance'] = (new DistanceCalculator(
                    new LatLong($latitude, $longitude),
                    new LatLong($v['门店纬度'], $v['门店经度'])
                ))->get()->asKilometres();
            }
            if ($distance > 0 && $list[$k]['distance'] > $distance) {//距离
                unset($list[$k]);
                continue;
            }
            if ($shopCode == $list[$k]['铺位号']) {//排除自己店铺
                unset($list[$k]);
                continue;
            }

            $data[] = [
                'shopName'     => $list[$k]['门店名称'],
                'distance'     => $list[$k]['distance'],
                'distanceText' => self::distanceText($list[$k]['distance']),
                'address'      => $list[$k]['店铺地址'],
                'shopCode'     => $list[$k]['铺位号'],
                'status'       => $list[$k]['状态'],
                'province'     => $list[$k]['门店所在省'],
                'city'         => $list[$k]['门店所在市'],
                'district'     => $list[$k]['区/县'],
                'openingTime'  => $list[$k]['开业日期'],
                'lon'          => $list[$k]['门店经度'],
                'lat'          => $list[$k]['门店纬度'],
            ];
        }
        if (!count($data)) {
            return [];
        }
        return collect($data)->sortBy('distance')->first();
    }

    /**
     * 距离文本展示
     * @param float $distance
     * @return int|string
     */
    public static function distanceText(float $distance)
    {
        if ($distance == 0) {
            return "";
        }
        if ($distance < 1) {
            return $distance > 0 ? round($distance * 1000, 2) . '米' : 0;
        } else {
            return round($distance, 2) . 'km';
        }
    }

    /**
     * 夸父开店-门店信息表-新表
     * https://kuafu.guandatacloud.com/data-source/r908e1ee76add42668f1adfc/details/overview?limit=50
     * @param int $shopCode
     * @param array $appendParams
     * @return array
     */
    public static function newShopList(int $shopCode = 0, array $appendParams = []): array
    {
        $params = [];

        if ($shopCode) {
           $params[] =
               [
                   'name'        => '铺位号',
                   'filterType'  => 'EQ',
                   'filterValue' => [
                       str_pad($shopCode, 4, '0', STR_PAD_LEFT)
                   ],
               ];
       }

        if ($appendParams) {
            $params[] = $appendParams;
        }


        $cacheKey = "tiger:openShop:map:guanyuan:newShopList:shopCode{$shopCode}:appendParams" . ':' . md5(json_encode($appendParams));

        return Cache::remember($cacheKey . $shopCode, 43200, function () use ($params) {
            return GuanyuanTool::fetch('r908e1ee76add42668f1adfc', 'de01da3ecf39743d895db6c6', $params, self::$timeout);
        });
    }

    /**
     * 网规容量
     * https://kuafu.guandatacloud.com/data-source/j9633ca0c7d034b709346af4/details/overview
     * @param string $province
     * @param string $city
     * @param string $district
     * @return array
     */
    public static function dotPlan(string $province = '', string $city = '', string $district = ''): array
    {
        $params = [];

        if ($province) {
           $params[] =
               [
                   'name'        => '省',
                   'filterType'  => 'EQ',
                   'filterValue' => [
                       $province
                   ],
               ];
       }

        $cacheKey = "tiger:openShop:map:guanyuan:dotPlan";

        return Cache::remember($cacheKey, 89400, function () use ($params) {
            return GuanyuanTool::fetch('j9633ca0c7d034b709346af4', 'j6d139e5a5d6e4899a9d03e4', $params, self::$timeout);
        });
    }


    /**
     * 通过门店code获得门店营业信息
     * @param array $shopCodes
     * @param int $day
     * @param int $source 如果是1就从观远拿  如果是0就从数据库拿
     * @return array
     * @throws GuzzleException
     */
    public static function getShopBusinessInfoByCode(array $shopCodes, int $day = 30, int $source = 0): array
    {
        $startDate = Carbon::now()->subDays($day)->toDateString();
        $endDate   = Carbon::now()->toDateString();

        if ($source == 0) {
            $data = [];
            GuanyuanSyncShopBusinessModel::query()
                ->whereBetween('date', [$startDate, $endDate])
                ->whereIn('code', $shopCodes)
                ->chunk(20, function ($shopBusinessList) use (&$data) {
                    foreach ($shopBusinessList as $shopBusiness) {
                        $data[] = $shopBusiness->toArray();
                    }
                });
            return $data;
        }

        $params    = [
            [
                'name'        => '日期',
                'filterType'  => 'GT',
                'filterValue' => [
                    $startDate
                ],
            ],
            [
                'name'        => '日期',
                'filterType'  => 'LE',
                'filterValue' => [
                    $endDate
                ],
            ],
            [
                'name'        => '门店编码',
                'filterType'  => 'IN',
                'filterValue' => $shopCodes,
            ]
        ];

        //详细信息
        return GuanyuanTool::fetch('h98d449754d534b8b990c4e3', 'r7e03eab637c04bdb838e887', $params, self::$timeout);
    }

    /**
     * 专职开发任务月度完成情况
     * @param array $param
     * @return array
     */
    public static function getMonthlyCompletionOfTasks(array $param = []): array
    {
        $condition = [];
        foreach ($param as $item) {
            $condition[] = $item;
        }

        $cacheKey = "tiger:openShop:map:guanyuan:getMonthlyCompletionOfTasks" . ':' . md5(json_encode($condition));

        return Cache::remember($cacheKey, 3600, function () use ($condition) {
            //详细信息
            return GuanyuanTool::fetch('e5c312f73fc464f448df0b05', 'd5a559a801a08420e9e17f7b', $condition, self::$timeout);
        });
    }


    /**
     * 夏季选址专项个人排名
     * @return array
     * @throws GuzzleException
     */
    public static function getPersonalSiteLocationConfirm(): array
    {
        return GuanyuanTool::fetch('m71f2fa0517b249e5afdeb83', 'n65cfa34440c346a69f45906', [], self::$timeout);
    }



    /**
     * 夏季选址专项团队排名
     * @return array
     * @throws GuzzleException
     */
    public static function getTeamSiteLocationConfirm(): array
    {
        return GuanyuanTool::fetch('a09b990b4088641f6833607f', 'lb8754ae2a67c4b7bb77a556', [], self::$timeout);
    }


}
